package org.dawning.shop.inventory.command.aggregate;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.axonframework.commandhandling.CommandHandler;
import org.axonframework.commandhandling.model.AggregateIdentifier;
import org.axonframework.eventhandling.EventHandler;
import org.axonframework.spring.stereotype.Aggregate;
import org.dawning.shop.common.commands.inventory.*;
import org.dawning.shop.common.domain.order.OrderId;
import org.dawning.shop.common.events.inventory.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static org.axonframework.commandhandling.model.AggregateLifecycle.apply;

/**
 * Created by Cc on 2017/6/8.
 */
@Aggregate
@Data
@AllArgsConstructor
@NoArgsConstructor
public class InventoryAggregate {
    Logger logger = LoggerFactory.getLogger(InventoryAggregate.class);

    @AggregateIdentifier
    private String id;
    /**
     *  商品库存数量
     */
    private Long amount;

    /**
     *  商品库存警告数量
     */
    private Long warnAmount;


    @CommandHandler
    public InventoryAggregate(CreateInventoryCommand command) {
        logger.info("apply create inventory command : " + command.toString());
        apply(new InventoryCreateEvent(command.getId(),command.getAmount(),command.getWarnAmount()));
    }

    @CommandHandler
    public void on(AddInventoryCommand command) {
        logger.info("apply Add inventory command : " + command.toString());
        apply(new InventoryAddEvent(command.getInventoryId(),command.getQuantity()));
    }

    @CommandHandler
    public void on(SubtractInventoryCommand command) {
        logger.info("apply Subtract inventory command : " + command.toString());
        apply(new InventorySubtractEvent(command.getInventoryId(),command.getQuantity()));
    }



    @EventHandler
    public void on(InventoryCreateEvent event){
        this.id = event.getId();
        this.amount = event.getAmount();
        this.warnAmount = event.getWarnAmount();
    }

    @EventHandler
    public void on(InventoryAddEvent event){
        logger.info("add productAmount for product: "+event);
       this.amount +=event.getQuantity();
    }

    @EventHandler
    public void on(InventorySubtractEvent event){
        logger.info("Subtract productAmount for product: "+event);
        this.amount -=event.getQuantity();
    }

    @EventHandler
    public void on(InventoryReleaseEvent event) {
        logger.info("add productAmount for product: "+event);
        this.amount +=event.getQuantity();
    }


    public void reserve(OrderId orderId,Long quantity){
        if(this.amount>quantity){
            apply(new InventoryReserveEvent(orderId,this.id,quantity));
        }else{
            apply(new InventoryNoEnoughEvent(orderId,id));
        }
    }


    @EventHandler
    public void on(InventoryReserveEvent event) {
        logger.info("reserve product: "+event.getQuantity());
        this.amount -=event.getQuantity();
        logger.info("remaining : "+this.amount);
    }

}
